#include "MemoryScan.h"
/*
SIZE_T WINAPI VirtualQuery(
  __in_opt  LPCVOID lpAddress,
  __out     PMEMORY_BASIC_INFORMATION lpBuffer,
  __in      SIZE_T dwLength
);*/

VOID cMemoryScan::ScanPages()
{
	MEMORY_BASIC_INFORMATION Mbi;
	DWORD Address = ScanFrom;
	PagesCount = 0;
	ScannedPagesSize = PAGE_SIZE;
	
	ScannedPages = (SCANNED_PAGE *)malloc(ScannedPagesSize);
	VirtualQuery((LPCVOID)Address, &Mbi, sizeof(Mbi));
	do
	{
		if(Mbi.State != MEM_FREE)
		{
			if( Mbi.Protect & (PAGE_READWRITE | PAGE_READONLY | PAGE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ | PAGE_EXECUTE_WRITECOPY) )
			{
				if (PagesCount >= (ScannedPagesSize / sizeof(SCANNED_PAGE)))
				{
					ScannedPagesSize += PAGE_SIZE;
					ScannedPages = (SCANNED_PAGE *)realloc(ScannedPages, ScannedPagesSize);
				}
				ScannedPages[PagesCount].PageAddress = Address;
				ScannedPages[PagesCount].PageSize = Mbi.RegionSize;
			
				PagesCount++;
			}
		}
		Address += Mbi.RegionSize;
	}while (VirtualQuery((LPCVOID)Address, &Mbi, sizeof(Mbi)));
}

DWORD cMemoryScan::SearchMemory(DWORD From, DWORD To,LPVOID Value, eValueType ValueType)
{

	switch(ValueType){
		case Byte: // 8bit
				
				for(DWORD i = From, j = 0; i <= ScanTo; i++){
					if( i >= ScannedPages[StaticPagesCount].PageAddress && i < (ScannedPages[StaticPagesCount].PageAddress + ScannedPages[StaticPagesCount].PageSize) ){
							if(*(BYTE*)i == *(BYTE*)Value){
								return i;
							}
						}

					else{
						if( i < ScannedPages[StaticPagesCount].PageAddress ) i = ScannedPages[StaticPagesCount].PageAddress -1;
						else if( i > (ScannedPages[StaticPagesCount].PageAddress + ScannedPages[StaticPagesCount].PageSize) ) StaticPagesCount++;

						if(StaticPagesCount == PagesCount) 
						 break;
					}
				}
				  break;
		case Word: // 16bit
				for(DWORD i = From, j = 0; i <= ScanTo; i++){
					if( i >= ScannedPages[StaticPagesCount].PageAddress && i+1 >= ScannedPages[StaticPagesCount].PageAddress
						&& i < (ScannedPages[StaticPagesCount].PageAddress + ScannedPages[StaticPagesCount].PageSize) && i+1 < (ScannedPages[StaticPagesCount].PageAddress + ScannedPages[StaticPagesCount].PageSize)){
							if(*(WORD*)i == *(WORD*)Value){
								return i;
							}
					}

					else{
						if( i < ScannedPages[StaticPagesCount].PageAddress ) i = ScannedPages[StaticPagesCount].PageAddress -1;
						else if( i > (ScannedPages[StaticPagesCount].PageAddress + ScannedPages[StaticPagesCount].PageSize) ) StaticPagesCount++;

						if(StaticPagesCount == PagesCount) 
						 break;
					}
				}
		break;
		case Dword: // 32bit
				for(DWORD i = From, j = 0; i <= ScanTo; i++){
					if( i >= ScannedPages[StaticPagesCount].PageAddress &&  i+3 >= ScannedPages[StaticPagesCount].PageAddress && i < (ScannedPages[StaticPagesCount].PageAddress + ScannedPages[StaticPagesCount].PageSize)
						&& i+3 < (ScannedPages[StaticPagesCount].PageAddress + ScannedPages[StaticPagesCount].PageSize)){
							if(*(DWORD*)i == *(DWORD*)Value){
								return i;
							}
						}

					else{
						if( i < ScannedPages[StaticPagesCount].PageAddress ) i = ScannedPages[StaticPagesCount].PageAddress -1;
						else if( i > (ScannedPages[StaticPagesCount].PageAddress + ScannedPages[StaticPagesCount].PageSize) ) StaticPagesCount++;

						if(StaticPagesCount == PagesCount) 
						 break;
					}
				}
		break;
		case Qword: // 64bit
				for(DWORD i = From, j = 0; i <= ScanTo; i++){
					if( i >= ScannedPages[StaticPagesCount].PageAddress && i+7 >= ScannedPages[StaticPagesCount].PageAddress && 
						i < (ScannedPages[StaticPagesCount].PageAddress + ScannedPages[StaticPagesCount].PageSize) && i+7 < (ScannedPages[StaticPagesCount].PageAddress + ScannedPages[StaticPagesCount].PageSize) ){
							if(*(long long*)i == *(DWORD*)Value){
								return i;
							}
						}

					else{
						if( i < ScannedPages[StaticPagesCount].PageAddress ) i = ScannedPages[StaticPagesCount].PageAddress -1;
						else if( i > (ScannedPages[StaticPagesCount].PageAddress + ScannedPages[StaticPagesCount].PageSize) ) StaticPagesCount++;

						if(StaticPagesCount == PagesCount) 
						 break;
					}
				}
		break;
		case Float: // float 
				for(DWORD i = From, j = 0; i <= ScanTo; i++){
					if( i >= ScannedPages[StaticPagesCount].PageAddress &&  i+3 >= ScannedPages[StaticPagesCount].PageAddress
						&& i < (ScannedPages[StaticPagesCount].PageAddress + ScannedPages[StaticPagesCount].PageSize) && i+3 < (ScannedPages[StaticPagesCount].PageAddress + ScannedPages[StaticPagesCount].PageSize) ){
							if(*(float*)i == *(DWORD*)Value){
								return i;
							}
						}

					else{
						if( i < ScannedPages[StaticPagesCount].PageAddress ) i = ScannedPages[StaticPagesCount].PageAddress -1;
						else if( i > (ScannedPages[StaticPagesCount].PageAddress + ScannedPages[StaticPagesCount].PageSize) ) StaticPagesCount++;

						if(StaticPagesCount == PagesCount) 
						 break;
					}
				}
		break;
		case Double: // double
				for(DWORD i = From, j = 0; i <= ScanTo; i++){
					if( i >= ScannedPages[StaticPagesCount].PageAddress && i+7 >= ScannedPages[StaticPagesCount].PageAddress
						&& i < (ScannedPages[StaticPagesCount].PageAddress + ScannedPages[StaticPagesCount].PageSize) && i+7 < (ScannedPages[StaticPagesCount].PageAddress + ScannedPages[StaticPagesCount].PageSize) ){
							if(*(double*)i == *(DWORD*)Value){
								return i;
							}
						}

					else{
						if( i < ScannedPages[StaticPagesCount].PageAddress ) i = ScannedPages[StaticPagesCount].PageAddress -1;
						else if( i > (ScannedPages[StaticPagesCount].PageAddress + ScannedPages[StaticPagesCount].PageSize) ) StaticPagesCount++;

						if(StaticPagesCount == PagesCount) 
						 break;
					}
				}
		break;
		case Text: // text
			int len = strlen((const char*)Value);
			
			for(DWORD i = From; i <= To; i++){
				if( i >= ScannedPages[StaticPagesCount].PageAddress && i < (ScannedPages[StaticPagesCount].PageAddress + ScannedPages[StaticPagesCount].PageSize) ){
					if(*(const char*)i == *(const char*)Value || *(const char*)i == ((*(const char*)Value) ^ CaseSensitiveVal ) )
						for(int l = 1, addr = i+1; l < len; l++, addr++){
							if(*(const char*)addr == *(const char*)((DWORD)Value+l) || *(const char*)addr == ((*(const char*)((DWORD)Value+l)) ^ CaseSensitiveVal))
								if(l == len - 1)
									return i;
								else
									continue;
							else
								break;
					}


				}

				else{
					if( i < ScannedPages[StaticPagesCount].PageAddress ) i = ScannedPages[StaticPagesCount].PageAddress -1;
					else if( i > (ScannedPages[StaticPagesCount].PageAddress + ScannedPages[StaticPagesCount].PageSize) ) StaticPagesCount++;

					if(StaticPagesCount == PagesCount) 
						break;
				}
		}
			break;
		}

	return NULL;
}

